/*********************************************************************************
 *      Copyright:  (C) 2025 iot25<lingyun@email.com>
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(03/05/25)
 *         Author:  iot25 <lingyun@email.com>
 *      ChangeLog:  1, Release initial version on "03/05/25 20:52:45"
 *                 
 ********************************************************************************/
#include <time.h>
#include <stdio.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>

#include "logger.h"
#include "get_time.h"
#include "get_temp.h"
#include "pack_data.h"
#include "socket.h"
#include "sqlite.h"

#define DEFAULT_LOG_FILE "client.log"
#define DEFAULT_DB_FILE "ds18b20.db"
#define DEFAULT_DEVICE_ID "001"
#define DEFAULT_INTERVAL 30


int print_usage(char *progname);
/* 函数声明 */

int main(int argc, char **argv)
{
    char                *hostname = NULL;                            
    int                  port = 0;                                    
    char                *device_id = DEFAULT_DEVICE_ID;                
    int                  interval_sec = DEFAULT_INTERVAL;             
    char                *db_name = DEFAULT_DB_FILE;                   
    char                *log_filename = DEFAULT_LOG_FILE;              
    int                  daemon_flag = 0;                             
    int                  sample_flag = 0;                             
    time_t               pretime = 0;                                 
    time_t               nowtime = 0;                                 
    char                 data[2048] = {0};                             
    socket_t             sock = {0};                                   
    packet_t             pack;                                         
    int                  ch = -1;
    int                  log_level = LOG_LEVEL_INFO;  // 改为使用logger.h定义的级别
    long                 log_size = 1024;
    int                  log_lock = 1;
    int   				 data_len = 0; 

	struct option        opts[] =                             
    {
        {"ipaddr", required_argument, NULL, 'i'},
        {"port", required_argument, NULL, 'p'},
        {"serial", required_argument, NULL, 's'},
        {"interval", required_argument, NULL, 't'},
        {"help", no_argument, NULL, 'h'},
        {"daemon", no_argument, NULL, 'd'},
        {NULL, 0, NULL, 0}
    };

    /*Parse command line arguments*/
    while( (ch = getopt_long(argc, argv, "i:p:s:t:h:q", opts, NULL)) != -1 )
    {
        switch( ch )
        {
            case 'i':
                hostname = optarg;          /* 服务器ip/主机名/域名 */
                break;
            case 'p':
                port = atoi(optarg);        /* 服务器端口号 */
                break;
            case 's':
                device_id = optarg;         /* 设备id */
                break;
            case 't':
                interval_sec = atoi(optarg);/* 采样时间间隔 */
                break;
            case 'd':
                daemon_flag = !daemon_flag;
                break;
            case 'h': 
                print_usage(argv[0]);       /* 打印帮助信息 */
                return 0;
        }
    }

    if( (!hostname) || (!port) )            /* 判断输入参数是否合法 */
    {                                           
        print_usage(argv[0]);               /* 打印帮助信息 */
        return 0;
    }

	if (daemon_flag)
    {
        daemon(1, 0);
        log_filename = DEFAULT_LOG_FILE;  // 强制使用日志文件
    }

    log_open(log_filename, log_level, log_size, log_lock);//初始日志系统

    if (socket_init(&sock, hostname, port) != 0)//初始化套接字
    {
        log_error("Socket initialization failed");
        return -1;
    }

    if ( db_init(db_name)!= 0 )              /* 初始化数据库 */
    {        
        log_error("database initialization failed\n");
        return -1;
    }

    pretime = 0;
    
	//Main loop - Continuously collect and send data
    while( 1 )
    {
        // 未采集 
        sample_flag = 0;                                                
        time(&nowtime);
        
		if ( difftime(nowtime , pretime) >= interval_sec )/* 判断是否到采集时间 */
        {                                                                
            memset(&pack, 0, sizeof(pack));

			//Set data packet content
            strncpy(pack.dev_id, device_id, sizeof(pack.dev_id));       /* 设备id */
            get_time(pack.dev_time);                                    /* get current time*/
            get_temp(&pack.dev_temp);									/* collect Temperature data*/
            
			log_info("Temperature sampled: %.2f°C at %s", pack.dev_temp, pack.dev_time);
			
			sample_flag = 1;                                            //mark sampling completed
            pretime = nowtime;
        }    
		
		//Check and maintain network connection
        if ( !sock.connected )           
        {        
            if (socket_connect(&sock) != 0) 
            {
            	log_error("socket_connect: Failed");
            	if( sample_flag == 1 )
				{
					 db_insert(&pack);
				}
				sleep(5);  // 避免频繁重连
            	continue;
        
			}
		}

		//If new data is sampled, pack and send it
        if ( sample_flag==1 )    
        {   
			log_debug("Before pack_data: dev_id=%s, dev_time=%s, dev_temp=%.2f\n", pack.dev_id, pack.dev_time, pack.dev_temp);
		 
			//pack data
			data_len = pack_data(&pack, data, sizeof(data));
     	    //data_len=pack_tlv(&pack, data, sizeof(data));
			//data_len=pack_data_json(&pack, data, sizeof(data));

			if (data_len > 0)
        	{
				//Attempt to send data via network
            	if (socket_write(&sock, data, data_len) < 0)
            	{
					log_warn("Network send failed, saving data to database");
                	db_insert(&pack);			//发送失败，保存到数据库
                	socket_close(&sock);		//关闭连接，后续会重新连接
            	}
            	else
            	{
                	log_info("pack data successfully\n");
            	}
        	}
        	else
        	{
            	log_error("pack data failure rv = %d\n",data_len);
        	}
        }
	
		//// Check if there's historical data pending transmission in database
        if ( 0 == db_query(&pack) )                            
        {
        
			data_len = pack_data(&pack, data, sizeof(data));                /* 将查询到的数据pack打包到data中 */

		   // Attempt to send historical data
            if ( data_len > 0 && socket_write(&sock, data, data_len) < 0 )    
            {                                                    
                socket_close(&sock);        // Close connection on failure                    
            }
            else
            {
                db_delete();                //Remove from database on success   
            }
         }
    }

	usleep(100000);  //100ms
    
	socket_close(&sock);
    db_close();
    log_close();
    return 0;
}

int print_usage(char *progname)
{
    if ( NULL == progname )
    {
        return -1;
        log_error("NULL pointer");
    }
    printf("%s usage: \n", progname);
    printf("-i(--ipaddr): sepcify server IP address or hostname or domain name.\n");
    printf("-p(--port): sepcify server port.\n");
    printf("-s(--serial): sepcify device serial number.\n");
    printf("-t(--time):sepcify sampling interval.\n");
    printf("-d,--daemon Run as daemon\n");
    printf("-h(--help): print help informatiom.\n");
    printf("\n");
    return 0;
}


